-- 生成指定位数长度的一个随机字符串ID
---@param length number ID长度, 默认8位
function GetRandomID(length)
    length = type(length) == "int" and length > 0 and math.floor(length) or 8
    local id = XS_RandomIDSeed[math.random(53)] -- 首位为大小写字母或下划线

    local seed_len = #XS_RandomIDSeed
    for _ = 1, length - 1 do
        id = id .. XS_RandomIDSeed[math.random(seed_len)]
    end

    return id
end

-- 比较
local compare_options = { "gt", "gte", "lt", "lte", "eq", "neq" }
---@param option table 比较参数表, neq为值或列表(不包含的值), 其余为值, 值:暂只支持字符串或数字
---@param value any 比较值, 暂只支持字符串/数字
function Compare(option, value)
    local res, pass = true, false
    local type_v = type(value)
    local neq_type = type(option["neq"])

    if type_v ~= "number" and type_v ~= "string" then
        return false
    end

    for _, v in pairs(compare_options) do
        if type(option[v]) == type_v or (v == "neq" and neq_type == "table") then
            pass = true
            break
        end
    end
    if not pass then
        return false
    end

    -- 大于等于/大于
    if res and type(option["gte"]) == type_v then
        res = value >= option["gte"]
    elseif res and type(option["gt"]) == type_v then
        res = value > option["gt"]
    end

    -- 小于等于/小于
    if res and type(option["lte"]) == type_v then
        res = value <= option["lte"]
    elseif res and type(option["lt"]) == type_v then
        res = value < option["lt"]
    end

    -- 等于
    if res and type(option["eq"]) == type_v then
        res = value == option["eq"]
    end

    -- 不等于
    if res and neq_type == "table" then
        -- 不包含
        for _, v in pairs(option["neq"]) do
            res = value ~= v
            if not res then
                break
            end
        end
    elseif res and neq_type == type_v then
        -- 不等于
        res = value ~= option["neq"]
    end

    return res
end

-- 浮点数(按4舍6入5成双计数保留法)
---@param value number 数值
---@param decimal_len number 保留小数位数
function Float(value, decimal_len)
    value = tostring(value)
    local value_type, integer, _, decimal = ReCheck(value, { "int", "decimal" })
    if not value_type then
        return 0
    end

    if type(decimal_len) == "number" and decimal_len >= 0 then
        decimal_len = math.floor(decimal_len)
    else
        decimal_len = 2
    end

    local res = ""

    if value < "0" then
        res = "-"
    end

    -- 整数
    res = res .. integer
    if value_type == "int" then
        return tonumber(res)
    end

    -- 保留为整数
    if decimal_len == 0 then
        local the_unit = string.sub(integer, -1)
        local tenth_place = string.sub(decimal, 1, 1)
        if tenth_place > "5" or (tenth_place == "5" and the_unit % "2" > 0) then
            return res + "1"
        end
        return tonumber(res)
    end

    -- 本身在保留位数内
    if #decimal <= decimal_len then
        return tonumber(res .. "." .. decimal)
    end

    res = res .. "." .. string.sub(decimal, 1, decimal_len)
    -- 保留指定位数小数
    local decimal_end = string.index(decimal, decimal_len)
    local rounding = string.index(decimal, decimal_len + 1)
    if rounding > "5" or (rounding == "5" and decimal_end % "2" > 0) then
        return res + "0." .. string.rep("0", decimal_len - 1) .. "1"
    end

    return tonumber(res)
end

-- 分段式数值
---@param value number 数值
---@param sep string 分割符, 默认","
---@param seg number 分割长度, 默认3
function NumSegmented(value, sep, seg)
    sep = type(sep) == "string" and sep or ","
    seg = type(seg) == "number" and seg > 1 and math.floor(seg) or 3
    local res = {}
    local value_type, integer, _, decimal = ReCheck(tostring(value), { "int", "decimal" })

    if not value_type then
        return "NaN"
    end

    -- 负数
    if value < 0 then
        table.insert(res, "-")
    end

    -- 整数部分处理
    local integer_len = string.len(integer)
    -- 头部
    local first = integer_len % seg
    if first > 0 then
        table.insert(res, string.sub(integer, 1, first))
        integer = string.sub(integer, first + 1)
        integer_len = integer_len - first
    end
    -- 各分段
    while integer_len > 0 do
        table.insert(res, string.sub(integer, 1, seg))
        integer = string.sub(integer, seg + 1)
        integer_len = integer_len - seg
    end

    -- 小数部分处理
    if value_type == "decimal" then
        table.insert(res, decimal)
    end

    return table.concat(res, sep)
end
